package Threads.Patterns;

import java.util.LinkedList;

//生产者消费者模式
//消息队列

//有一个套路需要记住，这里需要用while，条件不满足，就进入wait等待队列，等被唤醒之后，再判断是否满足条件
    /*  while（条件）
            wait（）；

     */
public class MessageQueue_ProducerAndConsumer {

    public static void main(String[] args) {
        MessageQueue messageQueue = new MessageQueue(3);
        for (int i=0;i<4;i++){
            int _i=i;
            new Thread(()->{
                try {
                    messageQueue.put(new Message(_i,"hello"+_i));
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            },"producer"+i).start();
        }
        new Thread(()->{
            while (true){
                try {
                    Thread.sleep(1000);
                    messageQueue.take();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"consumer").start();
    }

    public static class MessageQueue{

        //底层是双向链表，作为队列，实现消息队列
        private LinkedList<Message> list=new LinkedList<>();

        //容量
        private int capacity;

        public MessageQueue(int capacity){this.capacity=capacity;}

        public Message take() throws InterruptedException {
            synchronized (list){
                while (list.isEmpty()){
                    System.out.println("队列为空，消费者等待中----");
                    list.wait();
                }
                //拿队列中的第一个
                Message message = list.removeFirst();
                System.out.println("获取到了消息："+message);
                //唤醒生产者
                list.notifyAll();
                return message;
            }
        }

        public void put(Message message) throws InterruptedException {
            synchronized (list){
                while (list.size()>=capacity){
                    System.out.println("队列满，生产者等待中---");
                    list.wait();
                }
                list.add(message);
                System.out.println("已经生产消息："+message);
                //唤醒消费者
                list.notifyAll();
            }
        }
    }

    public final static class Message{
        private int id;
        private Object val;

        public Message(int id,Object val){
            this.id=id;
            this.val=val;
        }

        public int getId(){return id;}

        public Object getVal(){return val;}

        @Override
        public String toString() {
            return "Message{" +
                    "id=" + id +
                    ", val=" + val +
                    '}';
        }
    }
}
